package com.my.study.barrier;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * 使用volatile修饰object成员变量
 *
 * @author: yidujun
 * @create: 2021/04/29 10:49
 */
@Slf4j(topic = "c.ContainerOne")
public class ContainerOne {

    public static class SomeThing {
        private int status;

        public SomeThing() {
            status = 1;
        }

        public int getStatus() {
            return status;
        }
    }

    private volatile SomeThing object;

    public void create() {
        object = new SomeThing();
    }

    public SomeThing get() {
        while (object == null) {
            Thread.yield(); // 不加这句话可能会在此出现无限循环
        }
        return object;
    }

    public static void main(String[] args) throws InterruptedException {
        final int THREADS_COUNT = 20;
        final int LOOP_COUNT = 100000;

        long sum = 0;
        long min = Integer.MAX_VALUE;
        long max = 0;

        for (int n = 0; n <= 100; n++) {
            ContainerOne basket = new ContainerOne();
            List<Thread> putThreads = new ArrayList<>();
            List<Thread> takeThreads = new ArrayList<>();
            for (int i = 0; i < THREADS_COUNT; i++) {
                putThreads.add(new Thread(() -> {
                    for (int j = 0; j < LOOP_COUNT; j++) {
                        basket.create();
                    }
                }));

                takeThreads.add(new Thread(() -> {
                    for (int j = 0; j < LOOP_COUNT; j++) {
                        basket.get().getStatus();
                    }
                }));
            }
            long start = System.nanoTime();
            for (int i = 0; i < THREADS_COUNT; i++) {
                takeThreads.get(i).start();
                putThreads.get(i).start();
            }
            for (int i = 0; i < THREADS_COUNT; i++) {
                takeThreads.get(i).join();
                putThreads.get(i).join();
            }
            long end = System.nanoTime();
            long period = end - start;
            if (n == 0) {
                continue; //由于JIT的编译，第一次执行需要更多时间，将此时间不计入统计
            }
            sum += (period);
            if(period < min) {
                min = period;
            }
            if(period > max) {
                max = period;
            }
        }
        log.debug("Average: {}", sum / 100);
        log.debug("Max: {}", max);
        log.debug("Min: {}", min);
    }

}
